package com.share.gateway.utils;

import com.alibaba.fastjson.JSON;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.SignedJWT;
import com.share.common.enums.HttpStatusEnum;
import com.share.exception.CustomerAuthenticationException;
import com.share.properties.expTimeProperties;
import com.share.user.admin.dtos.PayloadDTO;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.util.Map;

/**
 * 获取token工具类
 */
@Component
public class TokenUtils {

    private final expTimeProperties exp;
    private final RSAKey rsaKey;

    public TokenUtils(expTimeProperties exp, RSAKey rsaKey) {
        this.exp = exp;
        this.rsaKey = rsaKey;
    }

    /**
     * 获取负载信息
     */
    public PayloadDTO getClaimsFromToken(String token) {
        //创建JWSObject
        try {
            SignedJWT signedJWT = SignedJWT.parse(token);
            //创建RSA验证器
            RSASSAVerifier verifier = new RSASSAVerifier(rsaKey);
            //验证签名
            signedJWT.verify(verifier);
            //获取负载信息
            Map<String, Object> Claims = signedJWT.getJWTClaimsSet().toJSONObject();
            return JSON.parseObject(JSON.toJSONString(Claims), PayloadDTO.class);
        } catch (ParseException | JOSEException e) {
            throw new CustomerAuthenticationException(HttpStatusEnum.UNAUTHORIZED.getMessage());
        }
    }

    private String createToken(PayloadDTO payloadDto){
        try {
            //设置jws头 设置签名算法和类型
            JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256)
                    .type(JOSEObjectType.JWT)
                    .build();
            payloadDto.setIat(System.currentTimeMillis());
            payloadDto.setExp(payloadDto.getIat()+exp.getExp());

            //将负载信息封装到payload
            Payload payload = new Payload(JSON.toJSONString(payloadDto));
            JWSObject jwsObject = new JWSObject(header,payload);
            //创建RSA签名器
            JWSSigner jwsSigner = new RSASSASigner(rsaKey,true);
            jwsObject.sign(jwsSigner);
            return jwsObject.serialize();
        } catch (JOSEException e) {
            throw new RuntimeException(e);
        }

    }


    /**
     * 获取token
     * @param payloadDto 封装对象
     * @return token
     */
    public String AccessToken(PayloadDTO payloadDto){
        return createToken(payloadDto);
    }

    /**
     * 获取刷新token
     */
    public String refreshToken(String token){
        PayloadDTO payloadDto = getClaimsFromToken(token);
        payloadDto.setExp(payloadDto.getIat()+ 2 * exp.getExp());
        return createToken(payloadDto);
    }

    /**
     * 返回当前token是否过期
     */
    public Boolean isTokenExpired(String token){
        PayloadDTO payloadDto = getClaimsFromToken(token);
        return System.currentTimeMillis() > payloadDto.getExp();
    }



    public String refreshHeadToken(String token){
        token = token.substring(7);
        PayloadDTO payloadDto = getClaimsFromToken(token);
        return AccessToken(payloadDto);
    }

    /**
     * 判断token在指定时间内是否刚刚刷新过
     * @param token 原token
     * @param time 指定时间（秒）
     */
    private boolean tokenRefreshJustBefore(String token, int time) {
        PayloadDTO payloadDto = getClaimsFromToken(token);
        Long iat = payloadDto.getIat();
        // 计算 30 分钟的毫秒值
        long thirtyMinutesInMillis = time * 1000L;
        return (System.currentTimeMillis() - thirtyMinutesInMillis) < iat;
    }


}
